/**
 * @(#)TaskRecordServiceImpl.java 2017年2月27日
 * Copyright(C) 2017 ZHEXIN IT CO.,LTD. All rights reserved.
 */
package org.jsbd.boss.service.impl;

import edu.hziee.common.queue.DelayExecuteBuffer;
import org.apache.commons.lang.StringUtils;
import org.jsbd.boss.dao.IApkSimulatorDAO;
import org.jsbd.boss.dao.IChannelApkLimitDAO;
import org.jsbd.boss.dao.ISimulatorLogDAO;
import org.jsbd.boss.dao.ITaskRecordLogDAO;
import org.jsbd.boss.domian.ChannelApkConfigTimeModel;
import org.jsbd.boss.domian.channel.*;
import org.jsbd.boss.enums.TaskTypeEnum;
import org.jsbd.boss.service.ApkManager;
import org.jsbd.boss.service.IApkSimulatorService;
import org.jsbd.boss.service.IChannelApkInfoService;
import org.jsbd.boss.service.ITaskRecordService;
import org.jsbd.boss.util.DateUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 任务记录
 * 
 * @author <a href="mailto:xupengcheng@zhexinit.com" >徐鹏程</a>
 * @version 1.0.0
 */
@Service
public class TaskRecordServiceImpl implements ITaskRecordService {
	public static final Logger LOGGER = LoggerFactory.getLogger(TaskRecordServiceImpl.class);

	@Resource(name = "taskRecordBuffer")
	private DelayExecuteBuffer<TaskRecord> taskRecordBuffer;

	@Resource
	private ITaskRecordLogDAO taskRecordLogDao;

	@Resource
	private IChannelApkLimitDAO channelApkLimitDAO;

	@Resource
	private IApkSimulatorDAO apkSimulatorDAO;

	@Resource
	private IChannelApkInfoService channelApkInfoService;

	@Resource
	private IApkSimulatorService apkSimulatorService;



	@Resource(name = "simulatorLogDao")
	private ISimulatorLogDAO simulatorLogDao;


	@Resource
	private ApkManager apkManager;

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.jsbd.boss.service.ITaskRecordService#addRecord(org.jsbd.boss.domian
	 * .channel.TaskRecord)
	 */
	@Override
	public void addRecord(TaskRecord taskRecord) {
		taskRecordBuffer.add(taskRecord);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.jsbd.boss.service.ITaskRecordService#selectRecords(org.jsbd.boss.
	 * domian.channel.TaskRecord)
	 */
	@Override
	public List<TaskRecord> selectRecords(TaskRecordVo taskRecordVo) {
		if (StringUtils.isBlank(taskRecordVo.getCurrDay())) {
			taskRecordVo.setCurrDay(DateUtil.getCurrentDateStr());
		} else {
			taskRecordVo.setCurrDay(taskRecordVo.getCurrDay().replace("-", ""));
		}
		String sysVer = taskRecordVo.getSysVer();
		Set<String> verSet = new HashSet<String>();
		if (StringUtils.isBlank(sysVer)) {
			taskRecordVo.setSysVer(null);
		} else {
			List<ChannelApkConfig> apkList = apkSimulatorDAO.getApkInfoList(taskRecordVo.getSysVer());
			for (ChannelApkConfig apkConfig : apkList) {
				verSet.add(apkConfig.getMark());
			}
		}
		Integer taskType = taskRecordVo.getTaskType();
		if (taskType == null || taskType == -1) {
			taskRecordVo.setTaskType(null);
		}
		return taskRecordLogDao.selectRecords(taskRecordVo);
	}

	/**
	 * 
	 * getExecTotal:查询半个小时之内的
	 * 
	 * @author <a href="mailto:xupengcheng@zhexinit.com" >徐鹏程</a>
	 * @return
	 */
	private Map<String, Integer> getExecTotal(String currDay, Integer taskType) {
		Calendar calendar = Calendar.getInstance();
		long now = System.currentTimeMillis();
		calendar.setTimeInMillis(now - 1800000);
		Date pre30 = calendar.getTime();
		Map<String, Integer> totalMap = new HashMap<String, Integer>();
		SimulatorLog log = new SimulatorLog();
		log.setTaskType(taskType);
		log.setCurrentDate(currDay);
		log.setCreateTime(pre30);
		List<ApkTaskInfo> result = simulatorLogDao.selectExecTask(log);
		if (result != null) {
			for (ApkTaskInfo taskInfo : result) {
				String key = taskInfo.getMark() + "_" + taskInfo.getCurrTime();
				totalMap.put(key, taskInfo.getExecTotal());
			}
		}
		return totalMap;
	}

	/**
	 * 
	 * updateRecords:查询任务记录更新记录表
	 * 
	 * @author <a href="mailto:xupengcheng@zhexinit.com" >徐鹏程</a>
	 */
	@Override
	public void updateRecords() {
		long start = System.currentTimeMillis();
		String currDay = DateUtil.getCurrentDateStr();
		Map<String, Integer> newTotalMap = getExecTotal(currDay, TaskTypeEnum.ADD_TASK.getType());
		Map<String, Integer> retentTotalMap = getExecTotal(currDay, TaskTypeEnum.RETENT_TASK.getType());
		List<ChannelApkConfig> apkInfos = channelApkInfoService.selectApkInfos(null);
		updateTaskExec(apkInfos, TaskTypeEnum.ADD_TASK.getType(), newTotalMap);
		updateTaskExec(apkInfos, TaskTypeEnum.RETENT_TASK.getType(), retentTotalMap);
		LOGGER.warn("任务分时段计算时间 {} ms", System.currentTimeMillis() - start);
	}

	private void updateTaskExec(List<ChannelApkConfig> apkInfos, Integer taskType, Map<String, Integer> totalMap) {
		String currDay = DateUtil.getCurrentDateStr();
		String current15Time = getCurrentTime().substring(9);
		String pre15Time = getPreCurrentTime().substring(9);
		for (ChannelApkConfig apkConfig : apkInfos) {
			String isDelete = apkConfig.getIsDelete();
			if (StringUtils.isNotBlank(isDelete) && "0".equals(isDelete)) {
				String apk = apkConfig.getMark();
				List<ChannelApkConfigTimeModel> apkConfigList = channelApkLimitDAO.selectChannelApkConfigTimeModel(apk, String.valueOf(taskType - 1));
				if (apkConfigList != null) {
					for (int i = 0; i < apkConfigList.size(); i++) {
						try {
							ChannelApkConfigTimeModel configTimeModel = apkConfigList.get(i);
							String time = configTimeModel.getTime();
							if (time.compareTo(current15Time) == 0 || (time.compareTo(pre15Time) == 0 && !pre15Time.equals("23:45:00"))) {// 计算当前或者上一个15分钟
								// mark 的 任务类型执行总量 和已执行总量
								int execTotal = 0, total = 0;
								String key = apk + "_" + currDay + " " + time.substring(0, 5);
								if (totalMap.containsKey(key)) {
									execTotal = totalMap.get(key);
								}
								TaskRecord record = new TaskRecord();
								record.setMark(apk);
								record.setSysVer(apkSimulatorService.getVer(apk));
								record.setTaskType(taskType);
								record.setCurrDay(Integer.parseInt(currDay));
								Integer dayLimit = apkConfig.getDaylimit();
								if (taskType == TaskTypeEnum.RETENT_TASK.getType()) {
									dayLimit = apkManager.getRetentTaskApkNum(apk);
									if (dayLimit == null) {
										continue;
									}
								}
								if (dayLimit == null) {
									dayLimit = 0;
								}
								Double currPercent = configTimeModel.getCurrPercent();
								if (currPercent == null) {
									currPercent = 0d;
								}
								BigDecimal totalB = new BigDecimal(currPercent * dayLimit / 100);
								total = totalB.setScale(0, BigDecimal.ROUND_HALF_UP).intValue();
								record.setTotal(total);
								record.setExecTotal(execTotal);
								record.setCurrTime(time);
								addRecord(record);
							}
						} catch (NumberFormatException e) {
							LOGGER.error("更新任务记录出错", e);
						}
					}
				}
			}
		}
	}

	private String getCurrentTime() {
		Calendar rightNow = Calendar.getInstance();
		SimpleDateFormat sdfMM = new SimpleDateFormat("mm");
		SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyMMdd HH");
		String current = sdf1.format(rightNow.getTime());
		int mm = Integer.parseInt(sdfMM.format(rightNow.getTime()));
		if (mm < 15) {
			current = current + ":00:00";
		} else {
			mm = (mm / 15) * 15;
			current = current + ":" + mm + ":00";
		}
		return current;
	}

	/**
	 * 
	 * getPreCurrentTime:上一个15分钟
	 * 
	 * @author <a href="mailto:xupengcheng@zhexinit.com" >徐鹏程</a>
	 * @return
	 */
	private String getPreCurrentTime() {
		Calendar rightNow = Calendar.getInstance();
		rightNow.setTimeInMillis(rightNow.getTimeInMillis() - 900000);
		SimpleDateFormat sdfMM = new SimpleDateFormat("mm");
		SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyMMdd HH");
		String current = sdf1.format(rightNow.getTime());
		int mm = Integer.parseInt(sdfMM.format(rightNow.getTime()));
		if (mm < 15) {
			current = current + ":00:00";
		} else {
			mm = (mm / 15) * 15;
			current = current + ":" + mm + ":00";
		}
		return current;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.jsbd.boss.service.ITaskRecordService#remove(org.jsbd.boss.domian.
	 * channel.TaskRecordVo)
	 */
	@Override
	public void remove(TaskRecordVo taskRecordVo) {
		taskRecordLogDao.remove(taskRecordVo);

	}
}
